package jhunter.rt.conf.ext;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jhunter.conf.app.vo.App;
import jhunter.conf.app.vo.DataSourceProperty;
import jhunter.conf.entities.vo.Entity;
import jhunter.dao.DaoFactory;
import jhunter.dao.EntityContainer;
import jhunter.dao.EntityExt;
import jhunter.dao.ddl.SchemaGenerator;
import jhunter.rt.JHunterSpringContext;
import jhunter.rt.conf.Node;
import jhunter.rt.conf.Reloadable;
import jhunter.security.JHunterAuthorizingRealm;
import jhunter.security.JHunterSecurityManger;
import jhunter.template.TemplateLoader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.realm.Realm;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.core.io.ByteArrayResource;

public class AppExt implements Reloadable {

	private static Log log = LogFactory.getLog(AppExt.class);

	private App app;

	private Node appNode;

	public AppExt(App app, Node appNode) {
		super();
		this.app = app;
		this.appNode = appNode;
	}

	public App getApp() {
		return app;
	}

	public void setApp(App app) {
		this.app = app;
	}

	public Node getAppNode() {
		return appNode;
	}

	public void setAppNode(Node appNode) {
		this.appNode = appNode;
	}

	public ModuleExt getModuleExt(String id) {
		List<Node> children = appNode.getChildren();
		for (Node node : children) {
			ModuleExt me = (ModuleExt) node.getObject();
			if (me.getModule().getId().equals(id)) {
				return me;
			}
		}
		return null;
	}

	private GenericXmlApplicationContext appContext;

	public GenericXmlApplicationContext getAppSpringContext() {
		return appContext;
	}

	protected void initAppContext() {
		synchronized (this) {
			Map<String, Object> params = new HashMap<String, Object>();
			List<DataSourceProperty> list = app.getDataSourceConfig().getDataSourceProperty();
			for (DataSourceProperty dataSourceProperty : list) {
				params.put(dataSourceProperty.getName(), dataSourceProperty.getValue());
			}
			String springXml = TemplateLoader.getStringByTemplate("/jhunter/service/app-spring-context.xml", params);
			log.trace("\n" + springXml);
			appContext = new GenericXmlApplicationContext(new ByteArrayResource(springXml.getBytes()));
//			SecurityUtils.setSecurityManager(appContext.getBean(JHunterSecurityManger.class));
			JHunterAuthorizingRealm realm = appContext.getBean(JHunterAuthorizingRealm.class);
			JHunterSecurityManger securityManger = JHunterSpringContext.getJHunterSpringContext().getBean(JHunterSecurityManger.class);
			//TODO 如果数据库信息是一致的，无须再创建一个重复的realm
			Collection<Realm> realms = securityManger.getRealms();
			if(realms == null) {
				realms = new ArrayList<Realm>();
			}
			realms.add(realm);
			securityManger.setRealms(realms);
		}
	}

	public void removeEntity(String id) {
		EntityContainer container = appContext.getBean(jhunter.dao.EntityContainer.class);
		container.remove(id);
		DaoFactory df = appContext.getBean(DaoFactory.class);
		df.removeDao(id);
	}

	public void registEntity(Entity e) {
		EntityContainer container = appContext.getBean(jhunter.dao.EntityContainer.class);
		EntityExt ee = new EntityExt(container, e);
		container.registEntityExt(ee);
	}

	public void mergeTable(List<String> entityIds) {
		EntityContainer container = appContext.getBean(jhunter.dao.EntityContainer.class);
		List<EntityExt> list = new ArrayList<EntityExt>();
		for (String id : entityIds) {
			EntityExt ee = container.getEntityExt(id);
			list.add(ee);
		}

		SchemaGenerator sg = appContext.getBean(SchemaGenerator.class);
		sg.create(list);
	}

	@Override
	public void unload() {
		// TODO Auto-generated method stub

	}

	private boolean createDDL = false;

	@Override
	public void afterLoad() {
		initAppContext();
		if (createDDL) {
			SchemaGenerator sg = appContext.getBean(SchemaGenerator.class);
			sg.create(this);
		}
	}

	@Override
	public void init() {
		afterLoad();
	}

}
